"""
选币策略回测框架，包含以下2个部分
1. 回测策略细节配置
2. 回测全局设置
"""
import os
from pathlib import Path

from core.utils.path_kit import get_folder_path

# ====================================================================================================
# ** 回测策略细节配置 **
# 需要配置需要的策略以及遍历的参数范围
# ====================================================================================================
# region 回测策略细节配置
start_date = '2021-01-01'  # 回测开始时间
end_date = '2024-07-24'  # 回测结束时间

backtest_name = '流动性多24H空12H策略'  # 回测的策略组合的名称。可以自己任意取。一般建议，一个回测组，就是实盘中的一个账户。
"""策略配置"""
strategy_list = [
    {
        # 策略名称。与strategy目录中的策略文件名保持一致。
        "strategy": "Strategy_默认策略",
        "offset_list": list(range(0, 1, 1)),
        "hold_period": "1D",
        "is_use_spot": True,
        # 资金权重。程序会自动根据这个权重计算你的策略占比，具体可以看1.8的直播讲解
        'cap_weight': 1,
        'long_cap_weight': 1,
        'short_cap_weight': 1,
        # ** 选择数量说明 **：
        # 我们会使用 pandas 中的 rank 函数排名。知识点：rank数值 从 1 开始，而不是 0；当 pct=True 的时候 0 < rank_pct < 1
        # - 当选币数量设置为：10 的时候，表示选出 rank <= 10 的币种，也可以写成 (0, 10)，表示 0 < rank <= 10
        # - 当选币数量设置为：(10, 20) 的时候，表示选出 10 < rank <= 20 的币种，也就是前 20 并不包含前 10 的币种
        # - 当选币数量设置为：0.1 的时候，表示选出 rank_pct <= 0.1 的币种，也就是前 10% 的币种
        # - 当选币数量设置为：(0.1, 0.2) 的时候，表示选出 0.1 < rank_pct <= 0.2 的币种，也就是前 20% 并不包含前 10% 的币种
        'long_select_coin_num': (0.1, 0.2),  # 选币数量范围，表示 10% < pct <= 20%，也可以写成 (10, 20)，表示 10 < rank <= 20
        'short_select_coin_num': (0.1, 0.2),  # 空头选项中特殊设置 `long_nums` 选项，表示空头数量和多头数量保持一致，不能用于区间
        # 选币因子信息列表，包含因子名，排序方式，参数，权重。
        "factor_list": [
            # 因子名（和factors文件中相同），True 表示从小到大排序，因子参数，权重：计算多因子加权排名使用。
            ('ILLQStd', True, 7, 1),
            # 可添加多个选币因子
        ],
        "filter_list": [
            # 因子名（和factors文件中相同），因子参数，过滤规则，True 表示从小到大排序
            ('PctChange', 7, 'pct:<0.8', True),

            # ** 因子过滤规则说明 **
            # 支持三种过滤规则：`rank` 排名过滤、`pct` 百分比过滤、`val` 数值过滤
            # - `rank:<10` 仅保留前 10 名的数据；`rank:>=10` 排除前 10 名。支持 >、>=、<、<=、==、!=
            # - `pct:<0.8` 仅保留前 80% 的数据；`pct:>=0.8` 仅保留后 20%。支持 >、>=、<、<=、==、!=
            # - `val:<0.1` 仅保留小于 0.1 的数据；`val:>=0.1` 仅保留大于等于 0.1 的数据。支持 >、>=、<、<=、==、!=
            # 可添加多个过滤因子和规则，多个条件将取交集
        ],
        "use_custom_func": False  # 使用系统内置因子计算、过滤函数
    }
]

# 策略配置
min_kline_num = 168  # 最少上市多久，不满该K线根数的币剔除，即剔除刚刚上市的新币。168：标识168个小时，即：7*24
black_list = ['BTC-USDT', 'ETH-USDT']  # 拉黑名单，永远不会交易。不喜欢的币、异常的币。例：LUNA-USDT, 这里与实盘不太一样，需要有'-'
white_list = []  # 如果不为空，即只交易这些币，只在这些币当中进行选币。例：LUNA-USDT, 这里与实盘不太一样，需要有'-'

# 模拟下单回测设置
account_type = '普通账户'  # '统一账户'或者'普通账户'
initial_usdt = 1_0000  # 初始资金
leverage = 1  # 杠杆数。我看哪个赌狗要把这里改成大于1的。高杠杆如梦幻泡影。不要想着一夜暴富，脚踏实地赚自己该赚的钱。
margin_rate = 0.05  # 维持保证金率，净值低于这个比例会爆仓

swap_c_rate = 8.5 / 10000  # 合约手续费(包含滑点)
spot_c_rate = 2 / 1000  # 现货手续费(包含滑点)

swap_min_order_limit = 5  # 合约最小下单量。最小不能低于5
spot_min_order_limit = 10  # 现货最小下单量。最小不能低于10

avg_price_col = 'avg_price_1m'  # 用于模拟计算的平均价，预处理数据使用的是1m，'avg_price_1m'表示1分钟的均价, 'avg_price_5m'表示5分钟的均价。
# endregion

# ====================================================================================================
# ** 回测全局设置 **
# 这些设置是客观事实，基本不会影响到回测的细节
# ====================================================================================================
# region 回测全局设置
job_num = os.cpu_count() - 2  # 回测并行数量

# ==== factor_col_limit 介绍 ====
factor_col_limit = 64  # 内存优化选项，一次性计算多少列因子。64是 16GB内存 电脑的典型值
# - 数字越大，计算速度越快，但同时内存占用也会增加。
# - 该数字是在 "因子数量 * 参数数量" 的基础上进行优化的。
#   - 例如，当你遍历 200 个因子，每个因子有 10 个参数，总共生成 2000 列因子。
#   - 如果 `factor_col_limit` 设置为 64，则计算会拆分为 ceil(2000 / 64) = 32 个批次，每次最多处理 64 列因子。
# - 对于16GB内存的电脑，在跑含现货的策略时，64是一个合适的设置。
# - 如果是在16GB内存下跑纯合约策略，则可以考虑将其提升到 128，毕竟数值越高计算速度越快。
# - 以上数据仅供参考，具体值会根据机器配置、策略复杂性、回测周期等有所不同。建议大家根据实际情况，逐步测试自己机器的性能极限，找到适合的最优值。


# 数据存储路径，填写绝对路径
# 使用官方准备的预处理数据，专门用于本框架回测使用，大幅提高速度
# 现货和合约1小时预处理数据（pkl格式）：https://www.quantclass.cn/data/coin/coin-binance-spot-swap-preprocess-pkl-1h
pre_data_path = '/Users/Shared/live/分享会/20241030/coin-binance-spot-swap-preprocess-pkl-1h-2024-10-29'

raw_data_path = Path(get_folder_path(pre_data_path))
# 现货数据路径
spot_path = raw_data_path / 'spot_dict.pkl'
# 合约数据路径
swap_path = raw_data_path / 'swap_dict.pkl'

# 回测结果数据路径。用于发帖脚本使用
backtest_path = Path(get_folder_path('data', '回测结果'))
backtest_iter_path = Path(get_folder_path('data', '遍历结果'))

# 稳定币信息，不参与交易的币种
stable_symbol = ['BKRW', 'USDC', 'USDP', 'TUSD', 'BUSD', 'FDUSD', 'DAI', 'EUR', 'GBP', 'USBP', 'SUSD', 'PAXG', 'AEUR']
# endregion


if len(pre_data_path) == 0:
    print('⚠️ 请先准确配置预处理数据的位置（pre_data_path）。建议直接复制绝对路径，并且粘贴给 pre_data_path')
    exit()

if (not spot_path.exists()) or (not swap_path.exists()):
    print(f'⚠️ 预处理数据不存在，请检查配置 `pre_data_path`: {pre_data_path}')
    exit()
